package disjunction
{
	import disjunction.Controller;
	import disjunction.View;
	import disjunction.state.State;
	import disjunction.state.StateChangeEvent;
	
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.Timer;

	/**
	 * A state using MVC architecture, which can be configured in terms of each of the
	 * three aspects of the triad. Initiates the processing cycle for real-time controllers.
	 * 
	 * @author Nick Wiggill
	 */

	public class GameState extends State
	{
		private static const ERROR_NEEDS_CONFIG:String = "Parameter must be an MVCStateConfig instance.";
		
		/** Generally the root context for the application */
		protected var _controller:Controller;
		protected var _view:View;
		
		/**
		 * @see disjunction.state.State
		 */
		public function GameState(id:String, model:Object, view:View, controller:Controller)
		{
			super(id);
			_view = view;
			_controller = controller;
			//D.I. -- this requires these properties to be public on the view and controller.
			//The reason for this is that if we want an "extends Controller/View" approach
			//(a good idea in view of the Principle of Least Astonishment) and also want D.I.
			//automated by the framework, then we cannot use the constructor to make these
			//"readonly" -- since as extended classes which could be anything, they cannot
			//be auto-created within the framework -- they must created outside. So manual
			//D.I. would be required. From a usability point of view, and considering that
			//certain languages do not support member access levels, this solution seems best.
			_view.model = model;
			_controller.model = model;
			_controller.view = _view;
		}
		
		/** 
		 * Initialise the state. (AS3 does not allow overrides to change
		 * method overloading, so an inline type check is done here instead.)
		 * @param config The MVCStateConfig instance to use for initialisation.
		 */
		public override function initialise(config:Object):void
		{
			if (!(config is GameStateConfig))
				throw new ArgumentError(GameState.ERROR_NEEDS_CONFIG);
			
			var config_:GameStateConfig = config as GameStateConfig;

			_view.initialise_(config_.view);
			_controller.initialise_(config_.controller);
		}

		/** Should be called only by StateManager. Do not call manually. */
		//TODO: make internal? (some pitfalls? language-specific?)
		public override function deactivate():void
		{
			super.deactivate();
			_controller.stop();
			//for each (var view:View in _views)
			//	view.stop();
			
			
			//TODO remove all event handlers assigned in init!
		}
		
		/** Should be called only by StateManager. Do not call manually. */
		private function redispatchStateChangeEvent(e:StateChangeEvent):void
		{
			e.fromStateId = this.id;
			dispatchEvent(e); //should auto-call event.clone()
		}
	}
}